package com.gee.spring.cloud.data.transform.core.center.config.handler;

import com.gee.spring.cloud.common.core.api.result.ApiResult;
import com.gee.spring.cloud.common.core.entity.center.config.DeviceMapping;
import com.gee.spring.cloud.common.starter.config.event.CenterConfigEventHandler;
import com.gee.spring.cloud.common.starter.feign.center.config.DeviceMappingClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;

import static cn.hutool.core.text.StrPool.UNDERLINE;

/**
 * @author gepengjun
 * @since 2024/3/19 14:31
 */
@Component
public class DeviceMappingHandler extends CenterConfigEventHandler<DeviceMapping> {

    //key: orgId_mappingDevId
    private final ConcurrentHashMap<String, DeviceMapping> deviceMappingMap = new ConcurrentHashMap<>();

    @Autowired
    private DeviceMappingClient deviceMappingClient;

    public DeviceMapping getByOrgIdAndMappingDevId(Long orgId, Long mappingDevId) {
        String key = buildKey(orgId, mappingDevId);
        return deviceMappingMap.computeIfAbsent(key, newKey -> deviceMappingClient.getByOrgIdAndMappingDevId(orgId, mappingDevId).getData());
    }

    @Override
    public void handlerUpdate(List<DeviceMapping> dataList, List<DeviceMapping> oldList) {
        dataList.forEach(deviceMapping ->{
            String key = buildKey(deviceMapping.getOrgId(), deviceMapping.getDevId());
            deviceMappingMap.computeIfPresent(key, (oldKey, old) -> deviceMapping);
        });
    }

    @Override
    public void handlerDelete(List<DeviceMapping> oldList) {
        oldList.forEach(deviceMapping -> {
            String key = buildKey(deviceMapping.getOrgId(), deviceMapping.getDevId());
            deviceMappingMap.remove(key);
        });
    }

    private static String buildKey(Long orgId, Long mappingDevId){
        return new StringJoiner(UNDERLINE).add(orgId.toString()).add(mappingDevId.toString()).toString();
    }


    public DeviceMapping getByOrgIdAndMappingDevIdentity(long orgId, long mappingDevIdentity) {
        Optional<DeviceMapping> deviceMappingOptional = deviceMappingMap.values().stream()
                .filter(deviceMapping -> deviceMapping.getMappingDevIdentity() == mappingDevIdentity)
                .findFirst();
        if (deviceMappingOptional.isPresent()){
            return deviceMappingOptional.get();
        }else {
            ApiResult<DeviceMapping> deviceMappingApiResult = deviceMappingClient.getByOrgIdAndMappingDevIdentity(orgId, mappingDevIdentity);
            return getFromApiResult(deviceMappingApiResult);
        }
    }

    public DeviceMapping getByOrgIdAndDevCode(long orgId, String devCode) {
        Optional<DeviceMapping> deviceMappingOptional = deviceMappingMap.values().stream()
                .filter(deviceMapping -> devCode.equals(deviceMapping.getMappingDevCode()))
                .findFirst();
        if (deviceMappingOptional.isPresent()){
            return deviceMappingOptional.get();
        }else {
            ApiResult<DeviceMapping> deviceMappingApiResult = deviceMappingClient.getByOrgIdAndMappingDevCode(orgId, devCode);
            return getFromApiResult(deviceMappingApiResult);
        }
    }

    public DeviceMapping getByOrgIdAndDevName(long orgId, String devName) {
        Optional<DeviceMapping> deviceMappingOptional = deviceMappingMap.values().stream()
                .filter(deviceMapping -> devName.equals(deviceMapping.getMappingDevName()))
                .findFirst();
        if (deviceMappingOptional.isPresent()){
            return deviceMappingOptional.get();
        }else {
            ApiResult<DeviceMapping> deviceMappingApiResult = deviceMappingClient.getByOrgIdAndMappingDevCode(orgId, devName);
            return getFromApiResult(deviceMappingApiResult);
        }
    }

    private DeviceMapping getFromApiResult(ApiResult<DeviceMapping> deviceMappingApiResult){
        DeviceMapping deviceMapping = deviceMappingApiResult.getData();
        if (deviceMappingApiResult.isSuccess() && deviceMapping != null){
            String key = buildKey(deviceMapping.getOrgId(), deviceMapping.getDevId());
            deviceMappingMap.put(key, deviceMapping);
            return deviceMapping;
        }else {
            return null;
        }
    }
}
